package com.zbkj.crmeb.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.common.CommonResult;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Joiner;
import com.utils.CrmebUtil;
import com.zbkj.crmeb.category.model.Category;
import com.zbkj.crmeb.category.model.CategoryMatch;
import com.zbkj.crmeb.category.service.CategoryService;
import com.zbkj.crmeb.category.vo.CategoryTreeVo;
import com.zbkj.crmeb.system.dao.SystemRoleDao;
import com.zbkj.crmeb.system.model.SystemAdmin;
import com.zbkj.crmeb.system.model.SystemRole;
import com.zbkj.crmeb.system.request.SystemRoleSearchRequest;
import com.zbkj.crmeb.system.service.SystemAdminService;
import com.zbkj.crmeb.system.service.SystemRoleService;

import lombok.extern.slf4j.Slf4j;

/**
* @author Mr.Zhang
* @Description SystemRoleServiceImpl 接口实现
* @since 2020-04-18
*/
@Slf4j
@Service
public class SystemRoleServiceImpl extends ServiceImpl<SystemRoleDao, SystemRole> implements SystemRoleService {
    @Resource
    private SystemRoleDao dao;
    @Autowired
    private SystemAdminService systemAdminService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SystemRoleService systemRoleService;

    /**
    * 列表
    * @param request 请求参数
    * @param pageParamRequest 分页类参数
    * @author Mr.Zhang
    * @since 2020-04-18
    * @return List<SystemRole>
    */
    @Override
    public List<SystemRole> getList(SystemRoleSearchRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<SystemRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(null != request.getStatus(), SystemRole::getStatus, request.getStatus());
        lambdaQueryWrapper.ne(SystemRole::getRoleName, "超级管理员");
        lambdaQueryWrapper.like(StringUtils.isNotBlank(request.getRoleName()), SystemRole::getRoleName, request.getRoleName());
        lambdaQueryWrapper.eq(null != request.getMerId(), SystemRole::getMerId, request.getMerId());
        
        if(Objects.nonNull(request.getIdentityType())){
            if(request.getIdentityType() != 2 && request.getIdentityType() != 6){
                lambdaQueryWrapper.eq(SystemRole::getIdentityType,request.getIdentityType());
            }else {
                lambdaQueryWrapper.in(SystemRole::getIdentityType, Arrays.asList(2,6));
            }
        }
        lambdaQueryWrapper.orderByAsc(SystemRole::getId);
        
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 根据id集合获取对应权限列表
     * @param ids id集合
     * @return 对应的权限列表
     */
    @Override
    public List<SystemRole> getListInIds(List<Integer> ids) {
//        LambdaQueryWrapper<SystemRole> lqw = new LambdaQueryWrapper<>();
//        lqw.in(SystemRole::getId, ids);
        return dao.selectBatchIds(ids);
    }

    /**
     * 检测是否有访问菜单接口取的权限
     * @param uri String 请求参数
     * @author Mr.Zhang
     * @since 2020-07-06
     * @return Boolean
     */
    @Override
    public Boolean checkAuth(String uri) {
        //查询当前路由是否配置了权限，如果没有配置则直接通过
        if(!categoryService.checkUrl(uri)){
            return true;
        }

        List<Integer> categoryIdList = getRoleListInRoleId(null);
        if(categoryIdList.size() < 1){
            return false;
        }

        //查询分类，根据in id和 路由
        return categoryService.checkAuth(categoryIdList, uri);
    }

    /**
     * 带结构的无线级分类
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public List<CategoryTreeVo> menu() {
        List<Integer> categoryIdList = getRoleListInRoleId(true);
        return categoryService.getListTree(Constants.CATEGORY_TYPE_MENU, 1, categoryIdList);
    }

    @Override
    public List<CategoryTreeVo> blackMenu() {
        List<Integer> categoryIdList = getRoleListInRoleId(false);
        return categoryService.getListTree(Constants.CATEGORY_TYPE_MENU, 1, categoryIdList);
    }

    @Override
    public CommonResult<String> deleteById(Integer id) {
        List<SystemAdmin> adminList = systemAdminService.list(Wrappers.lambdaQuery(SystemAdmin.class).eq(SystemAdmin::getIsDel, 0)
                .apply(CrmebUtil.getFindInSetSql("roles", id)));
        if(CollectionUtils.isNotEmpty(adminList)){
            throw new CrmebException("该身份下存在管理员,删除失败！");
        }
        return this.removeById(id) ? CommonResult.success() : CommonResult.failed();
    }
    
    @Override
    public Boolean deleteById2Mer(Integer id, Integer merId) {
    	List<SystemAdmin> adminList = systemAdminService.list(Wrappers.lambdaQuery(SystemAdmin.class)
    			.eq(SystemAdmin::getIsDel, 0)
    			.apply(CrmebUtil.getFindInSetSql("roles", id))
    			);
    	if(CollectionUtils.isNotEmpty(adminList)){
    		throw new CrmebException("该身份下存在管理员,删除失败！");
    	}
    	
    	boolean b = this.remove(Wrappers.<SystemRole>lambdaUpdate()
    			.eq(SystemRole :: getId, id)
    			.eq(SystemRole :: getMerId, merId)
    			);
    	
    	return b;
    }

    private List<Integer> getRoleListInRoleId(Boolean flag){
        //获取当前用户的所有权限
        SystemAdmin systemAdmin = systemAdminService.getInfo();
        if(null == systemAdmin || StringUtils.isBlank(systemAdmin.getRoles())){
            throw new CrmebException("没有权限访问！");
        }

        //获取用户权限组
        List<SystemRole> systemRoleList = getVoListInId(systemAdmin.getRoles());
        if(flag != null){
            systemRoleList = systemRoleList.stream().filter(e-> flag == (e.getIdentityType() != 6)).collect(Collectors.toList());
        }
        if(systemRoleList.size() < 1){
            throw new CrmebException("没有权限访问！");
        }

        //获取用户权限规则
        List<Integer> categoryIdList = new ArrayList<>();
        for (SystemRole systemRole : systemRoleList) {
            if(StringUtils.isBlank(systemRole.getRules())){
                continue;
            }

            categoryIdList.addAll(CrmebUtil.stringToArray(systemRole.getRules()));
        }

        return categoryIdList;
    }

    private List<SystemRole> getVoListInId(String roles) {
        LambdaQueryWrapper<SystemRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(SystemRole::getId, CrmebUtil.stringToArray(roles));
        return dao.selectList(lambdaQueryWrapper);
    }

	@Override
	public Boolean saveByEntity(SystemRole systemRole) {
		List<String> rules = Arrays.stream(systemRole.getRules().split(",")).collect(Collectors.toList());
		List<String> newRules = checkByParent(rules);
		systemRole.setRules(Joiner.on(",").join(newRules));
		
		return this.save(systemRole);
	}

	@Override
	public Boolean updateByEntity(SystemRole systemRole) {
		List<String> rules = Arrays.stream(systemRole.getRules().split(",")).collect(Collectors.toList());
		List<String> newRules = checkByParent(rules);
		systemRole.setRules(Joiner.on(",").join(newRules));
		
		return this.updateById(systemRole);
	}

	@Override
	public Boolean saveByMer(SystemRole systemRole) {
		// 检验新增角色是否有越权
		if(!checkMerRoles(systemRole)) {
			throw new CrmebException("请在权限内操作!");
		}
		List<String> rules = Arrays.stream(systemRole.getRules().split(",")).collect(Collectors.toList());
		List<String> newRules = checkByParent(rules);
		systemRole.setRules(Joiner.on(",").join(newRules));
		
		return this.save(systemRole);
	}

	@Override
	public Boolean updateByMer(SystemRole systemRole) {
		// 检验新增角色是否有越权
		if(!checkMerRoles(systemRole)) {
			throw new CrmebException("请在权限内操作!");
		}
		List<String> rules = Arrays.stream(systemRole.getRules().split(",")).collect(Collectors.toList());
		List<String> newRules = checkByParent(rules);
		systemRole.setRules(Joiner.on(",").join(newRules));
		
		return this.updateById(systemRole);
	}
	
	/**
	 * 校验管理员和他新增角色权限是否越权(新增编辑校验)
	 * @author daigb
	 * @date:  2022-12-01 11:48
	 */
	private Boolean checkMerRoles(SystemRole systemRole) {
		// 获取商户角色权限列表(不考虑多角色)
		List<String> rolesDB = Arrays.stream(systemAdminService.getInfo().getRoles().split(",")).collect(Collectors.toList());
		List<String> rulesDB = Arrays.stream(systemRoleService.getById(rolesDB.get(0)).getRules().split(",")).collect(Collectors.toList());
		log.info("--------------- 当前角色列表: {} ---------------", JSON.toJSONString(rulesDB));
		// 检验新增角色是否有越权
		List<String> rules = Arrays.stream(systemRole.getRules().split(",")).collect(Collectors.toList());;
		// 校验数据
		for(String role : rules) {
			if(!rulesDB.contains(role)) {
				log.info("--------------- 角色越权: {} ---------------", JSON.toJSONString(role));
				return false;
			}
		}
		
		return true;
	}
	
	/**
	 * 校验是否有未选的父类属性, 直接赋值
	 * @author daigb
	 * @date:  2022-12-09 11:17
	 */
	private List<String> checkByParent(List<String> rules) {
		// 待返回数据
		List<String> newRules = new ArrayList<>();
		newRules.addAll(rules);
		// 查询所有菜单
		List<Category> categorys = categoryService.list(Wrappers.<Category>lambdaQuery()
				.eq(Category :: getType, Constants.CATEGORY_TYPE_MENU)
				.eq(Category :: getStatus, 1)
				);
		Map<Integer, Category> categoryMap = categorys.stream().collect(Collectors.toMap(Category::getId, Function.identity()));
		// 匹配是否有父级未勾选
		for(String rule : rules) {
			Category vo = categoryMap.get(Integer.parseInt(rule));
			// 查询父级
			if(!Objects.isNull(vo) && (null != vo.getPid() && 0 != vo.getPid())) {
				if(!newRules.contains(vo.getPid().toString())) {
					newRules.add(vo.getPid().toString());
				}
			}
		}
		
		return newRules;
	}
	
}

